home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / CNews / Source / relay / sys.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-29  |  8.8 KB  |  356 lines

  1. /*
  2.  * news sys file reading functions
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <ctype.h>
  8. #include <string.h>
  9. #include <errno.h>
  10. #include "fixerrno.h"
  11. #include <sys/types.h>
  12. #include <sys/stat.h>
  13.  
  14. #include "libc.h"
  15. #include "fgetmfs.h"
  16. #include "news.h"
  17. #include "config.h"
  18. #include "batchnames.h"
  19. #include "ngmatch.h"
  20. #include "system.h"
  21.  
  22. #ifndef CMDPFX
  23. #define CMDPFX "uux - -r -z "    /* prefix of default command */
  24. #endif
  25. #define CMDSFX "!rnews"        /* suffix of same */
  26.  
  27. /* private */
  28. static FILE *fp = NULL;            /* stream for ctlfile(filerelname) */
  29. static char filerelname[] = "sys";    /* filename relative to $NEWSCTL */
  30.  
  31. /* forward decls */
  32. FORWARD char *parsecolon(), *reparse();
  33. FORWARD void readsys(), parsesysln(), parse(), parseflags(), newartfile();
  34. FORWARD int spacein();
  35.  
  36. /* exports */
  37. struct system *firstsys = NULL;    /* cache: 1st sys of in-core sys file */
  38. struct system *currsys = NULL;    /* current system */
  39.  
  40. /* imports */
  41. extern boolean donesys();
  42. extern struct system *mysysincache();
  43. extern void rewsys(), remmysys(), advcurrsys(), setupsys();
  44.  
  45. struct system *
  46. oursys()            /* return our sys entry */
  47. {
  48.     register struct system *sys = mysysincache();
  49.     static struct system fakesys;
  50.  
  51.     if (sys == NULL) {
  52.         register char *host = hostname();
  53.  
  54.         rewsys(fp);
  55.         while ((sys = nextsys()) != NULL && !STREQ(sys->sy_name, host))
  56.             ;
  57.         if (sys == NULL) {
  58.             /* no entry: cook one up; no need to malloc members */
  59.             sys = &fakesys;
  60.             sys->sy_name = host;
  61.             sys->sy_excl = NULL;
  62.             sys->sy_ngs = "all";
  63.             sys->sy_distr = sys->sy_ngs;
  64.             sys->sy_flags = 0;
  65.             sys->sy_lochops = 0;
  66.             sys->sy_cmd = "";
  67.             sys->sy_trngs = ngparse(strsave(sys->sy_ngs));
  68.             sys->sy_trdistr = sys->sy_trngs;
  69.             sys->sy_next = NULL;
  70.         }
  71.         remmysys(sys);            /* for future reference */
  72.     }
  73.     return sys;
  74. }
  75.  
  76. /*
  77.  * Return the next sys entry, which may span multiple lines.
  78.  * Returned pointer points at a struct whose lifetime (and that of its
  79.  * members) is not promised to last beyond the next call to nextsys();
  80.  * copy it and its pointed-to strings if you need them for longer.
  81.  *
  82.  * Note that readsys() reads one entry on small systems, but the entire
  83.  * sys file on big systems, so the common code in this file is subtle.
  84.  */
  85. struct system *
  86. nextsys()
  87. {
  88.     struct system *retsys;
  89.  
  90.     if (firstsys == NULL && fp == NULL)
  91.         if ((fp = fopenwclex(ctlfile(filerelname), "r")) == NULL)
  92.             return NULL;
  93.     if (fp != NULL && firstsys == NULL)
  94.         readsys();
  95.     retsys = currsys;
  96.     advcurrsys();
  97.     return retsys;
  98. }
  99.  
  100. /*
  101.  * On small systems, read one entry; else read whole sys file (done once only).
  102.  * Ignores '#' comments and blank lines; uses cfgetms to read possibly-
  103.  * continued lines of arbitrary length.
  104.  */
  105. STATIC void
  106. readsys()
  107. {
  108.     register char *sysline;
  109.  
  110.     setupsys(fp);        /* reuse currsys or rewind sys file */
  111.     while ((sysline = cfgetms(fp)) != NULL) {
  112.         if (sysline[0] != '#' && sysline[0] != '\n')
  113.             parsesysln(sysline);
  114.         free(sysline);
  115.         if (donesys())        /* early exit if on disk (small) */
  116.             return;
  117.     }
  118.     (void) nfclose(fp);
  119.     fp = NULL;
  120.     rewsys(fp);
  121. }
  122.  
  123. static char *curr, *next;            /* parsing state */
  124.  
  125. /*
  126.  * Parse (and modify) sysline into *currsys, which is malloced here
  127.  * and freed iff on a small system, in readsys(), see freecursys().
  128.  *
  129.  * Side-effect: sysline has a trailing newline removed.
  130.  */
  131. STATIC void
  132. parsesysln(sysline)
  133. register char *sysline;
  134. {
  135.     register struct system *sysp =(struct system *)nemalloc(sizeof *sysp);
  136.     char *flagstring;
  137.  
  138.     trim(sysline);
  139.     next = sysline;
  140.     parse(&sysp->sy_name);
  141.     parse(&sysp->sy_ngs);
  142.     parse(&flagstring);
  143.     parse(&sysp->sy_cmd);
  144.     errno = 0;
  145.     if (spacein(sysp->sy_name))
  146.         errunlock(
  147.         "whitespace in system name (or exclusions) of sys entry for `%s'",
  148.             sysp->sy_name);
  149.     if (spacein(sysp->sy_ngs))
  150.         errunlock(
  151.         "whitespace in newsgroups (or distributions) of sys entry for `%s'",
  152.             sysp->sy_name);
  153.     if (spacein(flagstring))
  154.         errunlock("whitespace in flags of sys entry for `%s'",
  155.             sysp->sy_name);
  156.     /* could check for extra fields here */
  157.  
  158.     parseflags(flagstring, sysp);
  159.     free(flagstring);        /* malloced by parse */
  160.     sysp->sy_next = NULL;
  161.  
  162.     /* reparse for embedded slashes */
  163.     sysp->sy_excl = reparse(sysp->sy_name, '/');
  164.     sysp->sy_distr = reparse(sysp->sy_ngs, '/');
  165.     /*
  166.      * N.B.: ngparse will chew up sy_ngs.  not copying sy_ngs saves
  167.      * a lot of memory when you have a big sys file.
  168.      */
  169.     sysp->sy_trngs = ngparse(sysp->sy_ngs);
  170.     if (sysp->sy_distr == NULL) {    /* default distr is ngs... */
  171.         sysp->sy_distr =   sysp->sy_ngs;
  172.         sysp->sy_trdistr = sysp->sy_trngs;
  173.     } else {
  174.         if (strchr(sysp->sy_distr, '/') != NULL)
  175.             errunlock(
  176.             "slash in distribution subfield of sys entry for `%s'",
  177.                 sysp->sy_name);
  178.         /* N.B.: ngparse will chew up sy_distr. */
  179.         sysp->sy_trdistr = ngparse(sysp->sy_distr);
  180.     }
  181.  
  182.     sysdeflt(sysp);            /* fill in any defaults */
  183.  
  184.     /* stash *sysp away on the tail of the current list of systems */
  185.     *(firstsys == NULL? &firstsys: &currsys->sy_next) = sysp;
  186.     currsys = sysp;
  187. }
  188.  
  189. STATIC int
  190. spacein(s)
  191. register char *s;
  192. {
  193.     return strchr(s, ' ') != NULL || strchr(s, '\t') != NULL;
  194. }
  195.  
  196. /*
  197.  * fill in defaults in sysp.
  198.  *
  199.  * expand a name of "ME" to hostname().
  200.  * If an empty batch file name was given, supply a default
  201.  * ($NEWSARTS/BTCHPFX system BTCHSFX).
  202.  * Prepend $NEWSARTS/BTCHDIR to relative file names.
  203.  * If an empty command was given, supply a default (uux - -r -z system!rnews).
  204.  * (This *is* yucky and uucp-version-dependent.)
  205.  */
  206. void
  207. sysdeflt(sysp)
  208. register struct system *sysp;
  209. {
  210.     if (STREQ(sysp->sy_name, "ME")) {
  211.         free(sysp->sy_name);    /* malloced by parse */
  212.         sysp->sy_name = strsave(hostname());
  213.     }
  214.     if (sysp->sy_flags&FLG_BATCH && sysp->sy_cmd[0] == '\0') {
  215.         register char *deffile =
  216.             str3save(BTCHPFX, sysp->sy_name, BTCHSFX);
  217.  
  218.         /* frees old sysp->sy_cmd, deffile */
  219.         newartfile(sysp, deffile);
  220.     } else if (sysp->sy_flags&FLG_BATCH && sysp->sy_cmd[0] != FNDELIM) {
  221.         register char *absfile = str3save(BTCHDIR, sysp->sy_cmd, "");
  222.  
  223.         /* frees old sysp->sy_cmd, absfile */
  224.         newartfile(sysp, absfile);
  225.     } else if (!(sysp->sy_flags&FLG_BATCH) && sysp->sy_cmd[0] == '\0') {
  226.         free(sysp->sy_cmd);    /* malloced by parse */
  227.         sysp->sy_cmd = str3save(CMDPFX, sysp->sy_name, CMDSFX);
  228.     }
  229. }
  230.  
  231. STATIC void
  232. newartfile(sysp, file)        /* replace sysp->sy_cmd with artfile(file) */
  233. register struct system *sysp;
  234. register char *file;
  235. {
  236.     free(sysp->sy_cmd);        /* malloced by parse */
  237. #ifdef BATCHSPOOL                /* UUNET special */
  238.     sysp->sy_cmd = str3save(BATCHSPOOL, SFNDELIM, file);
  239. #else
  240.     sysp->sy_cmd = strsave(artfile(file));
  241. #endif
  242.     free(file);
  243. }
  244.  
  245. /*
  246.  * Parse "next" to colon into malloced storage, return its ptr via "into".
  247.  * *into is freed iff on a small system, in readsys(), see freecursys().
  248.  */
  249. STATIC void
  250. parse(into)
  251. register char **into;
  252. {
  253.     curr = next;
  254.     if (curr == NULL)
  255.         *into = strsave("");
  256.     else {
  257.         next = parsecolon(curr);
  258.         *into = strsave(curr);
  259.     }
  260. }
  261.  
  262. STATIC char *
  263. parsecolon(line)        /* return NULL or ptr. to byte after colon */
  264. char *line;
  265. {
  266.     register char *colon;
  267.  
  268.     STRCHR(line, ':', colon);
  269.     if (colon != NULL)
  270.         *colon++ = '\0';
  271.     return colon;
  272. }
  273.  
  274. /*
  275.  * replace "delim" in "field" with a NUL and return the address of the byte
  276.  * after the NUL (the address of the second subfield), or NULL if no
  277.  * "delim" was present.
  278.  */
  279. STATIC char *
  280. reparse(field, delim)
  281. char *field;
  282. int delim;
  283. {
  284.     register char *delimp = strchr(field, delim);
  285.  
  286.     if (delimp != NULL)
  287.         *delimp++ = '\0';
  288.     return delimp;
  289. }
  290.  
  291. /*
  292.  * Parse sys file flags into sysp.
  293.  */
  294. STATIC void
  295. parseflags(flags, sysp)
  296. register char *flags;
  297. register struct system *sysp;
  298. {
  299.     sysp->sy_flags = 0;
  300.     sysp->sy_lochops = 0;        /* default L value */
  301.     errno = 0;
  302.     for (; *flags != '\0'; flags++)
  303.         switch (*flags) {
  304.         case 'A':
  305.             errunlock("A news format not supported", "");
  306.             /* NOTREACHED */
  307.         case 'B':        /* mostly harmless */
  308.             break;
  309.         case 'f':
  310.             sysp->sy_flags |= FLG_BATCH|FLG_SZBATCH;
  311.             break;
  312.         case 'F':
  313.             sysp->sy_flags |= FLG_BATCH;
  314.             break;
  315.         case 'I':        /* NNTP hook: write msgids, !files */
  316.             sysp->sy_flags |= FLG_BATCH|FLG_IHAVE;
  317.             break;
  318.         case 'L':        /* Ln */
  319.             sysp->sy_flags |= FLG_LOCAL;
  320.             sysp->sy_lochops = 0;
  321.             while (isascii(flags[1]) && isdigit(flags[1])) {
  322.                 sysp->sy_lochops *= 10;
  323.                 sysp->sy_lochops += *++flags - '0';
  324.             }
  325.             break;
  326.         case 'm':        /* send only moderated groups */
  327.             sysp->sy_flags |= FLG_MOD;
  328.             break;
  329.         case 'N':
  330.             errunlock(
  331.     "The N flag is a wasteful old kludge; see the I flag instead.", "");
  332.             /* NOTREACHED */
  333.         case 'n':        /* NNTP hook: write files+msgids */
  334.             sysp->sy_flags |= FLG_BATCH|FLG_NBATCH;
  335.             break;
  336.         case 'u':        /* send only unmoderated groups */
  337.             sysp->sy_flags |= FLG_UNMOD;
  338.             break;
  339.         case 'U':        /* mostly harmless */
  340.             break;
  341.         case 'H':        /* write history entry? sorry */
  342.         case 'S':    /* duplicate the work of the shell.  bzzt */
  343.         case 'M':        /* multicast: obs., see batcher */
  344.         case 'O':        /* multicast: obs., see batcher */
  345.         default:
  346.             errunlock("unknown sys flag `%s' given", flags);
  347.             /* NOTREACHED */
  348.         }
  349. }
  350.  
  351. void
  352. rewndsys()
  353. {
  354.     rewsys(fp);
  355. }
  356.